#include "Math.h"

const float Math<float>::PI = 4*atan(1.0);
const float Math<float>::TWO_PI = 2*PI;
const float Math<float>::HALF_PI = 0.5*PI;

template <class Real> 
static int Math<Real>::iabs( int iv )
{
	return ( iv >= 0 ? iv : -iv );
}

template <class Real>
int Math<Real>::iceil( float fv )
{
	return int( ceil(fv) );
}

template <class Real>
int Math<Real>::ifloor( float fv )
{
	return int( floor(fv) );
}

template <class Real>
int Math<Real>::isign( int iv )
{
	return ( iv > 0 ? +1 : ( iv < 0 ? -1 : 0 ));
}

template <class Real>
Real Math<Real>::abs( Real fv )
{
	return Real( fabs(fv) );
}

template <class Real>
Real Math<Real>::acos_t( Real fv )
{
	if ( -1.0 < fv )
	{
		if ( fv < 1.0 )
			return Real( acos(fv) );
		else
			return 0.0;
	}
	else
	{
		return PI;
	}
}

template <class Real>
Real Math<Real>::asin_t( Real fv )
{
	if ( -1.0 < fv )
	{
		if ( fv < 1.0 )
			return Real(asin(fv));
		else
			return -HALF_PI;
	}
	else
	{
		return HALF_PI;
	}
}

template <class Real>
Real Math<Real>::atan_t( Real fv )
{
	return Real( atan( fv ) );
}

template <class Real>
Real Math<Real>::atan2_t( Real fx, Real fy )
{
	return Real( atan2( fy, fx ) );
}

template <class Real>
Real Math<Real>::ceil_t( Real fv )
{
	return Real( ceil(fv) );
}

template <class Real>
Real Math<Real>::cos_t( Real fv )
{
	return Real(cos(fv));
}

template <class Real>
Real Math<Real>::exp_t( Real fv )
{
	return Real( exp( fv ));
}

template <class Real>
Real Math<Real>::floor_t( Real fv )
{
	return Real( floor( fv ));
}

template <class Real>
Real Math<Real>::log_t( Real fv )
{
	return Real( log(fv) );
}

template <class Real>
Real Math<Real>::pow_t( Real fb, Real fe )
{
	return Real( pow(fb, fe));
}

template <class Real>
Real Math<Real>::sign_t( Real fv )
{
	if ( fv > 0.0 )
		return 1.0;

	if ( fv < 0.0 )
		return -1.0;

	return 0.0;
}

template <class Real>
Real Math<Real>::sin_t( Real fv )
{
	return Real( sin(fv) );
}

template <class Real>
Real Math<Real>::sqrt_t( Real fv )
{
	return Real( sqrt(fv) );
}

template <class Real>
Real Math<Real>::invsqrt( Real fv )
{
	return (Real) (1.0 / sqrt((double) fv));
}


template <class Real>
Real Math<Real>::sqr( Real fv )
{
	return fv * fv;
}

template <class Real>
Real Math<Real>::unit_random()
{
	return Real( rand()/Real(RAND_MAX) );
}

template <class Real>
Real Math<Real>::symmetric_random()
{
	return 2*Real( rand() ) / Real(RAND_MAX) - 1.0;
}
